#pragma once
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
//#include <netinet/in.h>
#include <wait.h>
#include <signal.h>
#include "ThreadPool.hpp"
#include "task.hpp"
#include "log.hpp"
#include "daemon.hpp"

string defaultip = "0.0.0.0";
uint16_t defaultport = 8000;
const int back = 2;  //连接请求队列个数,一般2-4

Log log;

enum
{
    SOCK_ERR = 1,
    BIND_ERR,
    LIStEN_ERR
};

class server;
struct thread_data
{
    int _fd;
    string _ip;
    uint16_t _port;
    server* ser;
};

class server
{
public:
    server(const string ip = defaultip, const uint16_t port = defaultport)
    {
        _ip = defaultip;
        _port = defaultport;
    }

    void init()
    {
        _listensock = socket(AF_INET, SOCK_STREAM, 0);
        if (_listensock < 0)
        {
            log.logmessage(fatal, "socket create error");
            exit(SOCK_ERR);
        }
        log.logmessage(info, "socket create success:%d", _listensock);

        sockaddr_in local;
        memset(&local, 0, sizeof(local));
        local.sin_family = AF_INET;
        inet_aton(_ip.c_str(), &local.sin_addr);
        local.sin_port = htons(_port);

        int opt = 1;
        //防止偶发性的服务器无法立即重启
        setsockopt(_listensock, SOL_SOCKET, SO_REUSEADDR|SO_REUSEPORT, &opt, sizeof(opt));

        //绑定
        if (bind(_listensock, (const struct sockaddr*)&local, sizeof(local)) < 0)
        {
            log.logmessage(fatal, "bind error:%s",strerror(errno));
            exit(BIND_ERR);
        }
        log.logmessage(info, "bind success");

        //tcp面向连接,服务器一般被动,处于一种等待连接到来的状态
        // 设置listen状态
        if (listen(_listensock, back) < 0)
        {
            log.logmessage(fatal, "listen error");
            exit(LIStEN_ERR);
        }
    }

    void service(int fd, const string ip, const uint16_t port)
    {
        cout << "welcome " << ip << endl;
        char message[1024];
        while (true)
        {    
            ssize_t n = read(fd, message, sizeof(message) - 1);
            if (n > 0)
            {
                message[n] = 0;
                //数据处理
                string echo_string;
                echo_string = "[" + ip + ":" + to_string(port) + "]: " + message;
                cout << echo_string << endl;

                write(fd, echo_string.c_str(), echo_string.size());
            }
            //读到0和其他情况
        }

    }

    static void* routine(void* tmp)
    {
        //线程分离
        pthread_detach(pthread_self());
        //可以service函数提到类外
        //添加一个类成员
        thread_data *td = static_cast<thread_data*>(tmp);
        td->ser->service(td->_fd, td->_ip, td->_port);

        delete td;
        return nullptr;
    }

    void run() 
    {
        //signal(SIGPIPE, SIG_IGN);
        pool<task>::GetInstance()->start();
        // 忽视子进程
        //signal(SIGCHLD, SIG_IGN);
        while (true)
        {
            //获取链接
            struct sockaddr_in sock;
            socklen_t len = sizeof(sock);
            int sockfd = accept(_listensock, (sockaddr *)&sock, &len);
            if (sockfd < 0)
            {
                log.logmessage(warning, "accept fail");
                continue;
            }

            char buff[32];
            string clientip = inet_ntop(AF_INET, &sock.sin_addr, buff, len);
            uint16_t clientport = ntohs(sock.sin_port);
            log.logmessage(info, "get a new link,sockfd:%d", sockfd);
 
            //多进程
            pid_t pid = fork();
            if (pid == 0)
            {
                // 子进程，孙子进程执行,子进程直接回收
                close(_listensock);
                if (fork() > 0)
                    exit(0); // 孙子进程,system领养
                service(sockfd, clientip, clientport);
                close(sockfd);
                exit(0);
            }
            // 父进程
            pid_t ret = waitpid(pid, nullptr, 0);
            close(sockfd);
        }
    }

    ~server()
    {
        close(_listensock);
    }

private:
    int _listensock;
    string _ip;
    uint16_t _port;
};